﻿#region Librerias

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Data.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using ESF.General;
using ESF.General.Entity;
using ESF.General.Text;
using ESF.SFT.Entities;
using ESF.SFT.FileUploader.Config;
using Ionic.Zip;
using Microsoft.Win32;
using System.Collections.ObjectModel;
using System.Text;
using System.ComponentModel;
using System.Globalization;
using ESF.WinForms;
using ESF.WinForms.Elements;
using ESF.SFT.FileUploader.Presenter.FileSelection;
using ESF.SFT.FileUploader.SharedResources;
using ESF.General.Network;
using ESF.SFT.FileUploader.Presenter.FileReceiver;
using System.Reflection;
using ESF.SFT.FileUploader.Helpers;

#endregion


namespace ESF.SFT.FileUploader
{
	/// <summary>
	/// Interaction logic for MainWindow.xaml
	/// </summary>
	public partial class FileUploaderWindow : BaseWPFWindow, IFileUploaderWindowViewer
	{
		#region Constantes

		private const string PARTCONF_AUTOENTRYFOLDER = "_aef.cfg";

		#endregion


		#region Miembros

		private FileUploaderWindowPresenter _Presenter;

		private OpenFileDialog _FileDialog;

		private System.Windows.Forms.FolderBrowserDialog _FolderDialog;

		private PaggingInfo _PaggingInfo;

		private ConfigureDigitalFileSign _ConfigureDigitalFileSign;

		private ObservableCollection<FileData> _SelectedFiles;

		private ValidationLogViewer _ValidationLogViewer;

		private List<FileSystemWatcher> _FSWatchers;

		private FileSystemWatcher _FolderDialogFSW;

		private BackgroundWorker _BgUpload;

		private BackgroundWorker _BgValidate;

		private int _SentFileCount;
		private int _ValidFileCount;
		private bool _WasConfirmMsgShowed;
		
		#endregion


		#region Propiedades

		public static string[] ExtensionFilters
		{
			get
			{
				List<string> extensions;


				extensions = new List<string>();

				foreach (string[] exts in (from FRVS in Program.FileRegisterValidatorSets select FRVS.AcceptedExtensions))
				{
					if (!DataHelper.IsEmpty(exts))
					{
						foreach (string ext in exts)
						{
							if (!extensions.Contains(ext.ToLower()))
							{
								extensions.Add(ext.ToLower());
							}
						}
					}
				}

				return extensions.ToArray();
			}
		}

		#endregion


		#region Constructor

		public FileUploaderWindow()
			: base()
		{
			InitializeComponent();

			imgInfo.Source = WinFormsHelper.ToBitmapSource (SharedImages.Info_32x32);

			imgSelectedFiles.Source = WinFormsHelper.ToBitmapSource(SharedImages.Computer_64x64);

			imgSentFiles.Source = WinFormsHelper.ToBitmapSource(SharedImages.HardDiskServer_64x64);

			Icon = WinFormsHelper.ToBitmapSource(SharedImages.Upload_64x64);


			_Presenter = new FileUploaderWindowPresenter (this);
			_Presenter.Load();

			IncludeVersionInTitle();

			_FileDialog = new OpenFileDialog ();
			_FileDialog.CheckFileExists = true;
			_FileDialog.Multiselect = true;
			_FileDialog.Title = "Archivo(s) a validar y enviar";


			_FolderDialog = new System.Windows.Forms.FolderBrowserDialog ();
			_FolderDialog.ShowNewFolderButton = true;
			_FolderDialog.Description = "Carpeta de Entrada Automática";


			_FolderDialogFSW = new FileSystemWatcher ();
			_FolderDialogFSW.EnableRaisingEvents = false;
			_FolderDialogFSW.IncludeSubdirectories = false;
			_FolderDialogFSW.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime;
			_FolderDialogFSW.Changed += _FolderDialogFSW_Changed;


			_ValidationLogViewer = new ValidationLogViewer ();

			_ConfigureDigitalFileSign = new ConfigureDigitalFileSign ();
			_ConfigureDigitalFileSign.Changed += _ConfigureDigitalFileSign_Changed;
			

			_PaggingInfo = new PaggingInfo ();
			_PaggingInfo.PageSize = 10;
			
			_SelectedFiles = new ObservableCollection<FileData> ();

			grvSelectedFiles.DataContext = _SelectedFiles;


			_FSWatchers = new List<FileSystemWatcher> ();
						
						
			_BgUpload = new BackgroundWorker();
			_BgUpload.DoWork += delegate(object s, DoWorkEventArgs eg) { UploadFiles ((bool) eg.Argument); };
			_BgUpload.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_BgUpload_RunWorkerCompleted);


			_BgValidate = new BackgroundWorker();
			_BgValidate.DoWork += DoDropFiles;
			_BgValidate.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_BgValidate_RunWorkerCompleted);

			ShowUploadHistory();
		}

		#endregion


		#region Funciones

		public void ShowUploadHistory ()
		{
			BrowseResults<FileReceiveLog> history;

			
			CurrentStepName = "Obteniendo historico de carga";

			Dispatcher.Invoke((Action)(() =>
			{
						
				try
				{
					Cursor = Cursors.Wait;
					
					Validate.VerifyDateRange (
						lblTitleStartUploadDate.Content.ToString (), dtmStartUploadDate.SelectedDate, 
						lblTitleEndUploadDate.Content.ToString (), dtmEndUploadDate.SelectedDate);

					history = _Presenter._ReceiverGeneralClient.GetFileUploadHistory (
						new FileReceiveLog ()
						{
							filStartUploadDateTime = DataHelper.SetAsStartDate (dtmStartUploadDate.SelectedDate),
							filEndUploadDateTime = DataHelper.SetAsEndDate (dtmEndUploadDate.SelectedDate),
							UploadUserAlias = Log.Session_UserName
						},_PaggingInfo);

					grvUploadFileHistory.ItemsSource = null;
					grvUploadFileHistory.ItemsSource = history.Results;

					_PaggingInfo = history.PaggingInfo;

					if (DataHelper.IsEmpty (history))
					{
						lblPageResumen.Content = "No hay resultados";	
					}
					else
					{
						lblPageResumen.Content = string.Format ("Página {0} de {1} para {2}", _PaggingInfo.PageIndex + 1, _PaggingInfo.PageCount, _PaggingInfo.RowCount);
					}				

					btngrvUploadFileHistoryNext.IsEnabled = _PaggingInfo.IsThereNext;
					btngrvUploadFileHistoryPrevious.IsEnabled = _PaggingInfo.IsTherePrevious;
					
					ShowResumen ();

					SetStatus ("Historico de carga completo.");
				}
				catch (Exception pEx)
				{
					SetStatusErrorDefTime (pEx);
				}

				Log.StopOps();

			
				Cursor = Cursors.Arrow;
			}));
		}


		private void ActiveFileSelectedButtons ()
		{
			Dispatcher.Invoke ((Action) (() => 
			{
				btnUploadFiles.IsEnabled = _SelectedFiles.Where (sf => sf.IsValid).Count () > 0;

				btnRemoveFile.IsEnabled = _SelectedFiles.Count > 0;

				lblgrvSelectedFilesCount.Content = 
					string.Format ("Ha seleccionado {0} archivos: {1} OK y {2} ER", 
						grvSelectedFiles.Items.Count, 
						_SelectedFiles.Count (sf=> sf.IsValid),
						_SelectedFiles.Count (sf=> !sf.IsValid));
			}));
		}


		private void ShowSelectFiles ()
		{
			if (_FileDialog.ShowDialog (this) == true)
			{
				DropFiles (_FileDialog.FileNames);
			}
		}


		private void SetStatusError(Exception pEx)
		{
			SetStatusError (pEx, null);
		}


		private void SetStatusError(Exception pEx, string pExtraMessage)
		{
			lblStatusBarText.Content = "Error";

			Log.Error(pEx);

			Dispatcher.Invoke ((Action) (() => { MessageBox.Show (this, (string.IsNullOrWhiteSpace(pExtraMessage) ? string.Empty : pExtraMessage + "\n\n") + GenericException.GetClientMessage(pEx), "Error", MessageBoxButton.OK, MessageBoxImage.Error); }));
		}


		private void SetStatusErrorDefTime (Exception pEx)
		{
			SetStatusErrorDefTime (pEx, null);
		}


		private void SetStatusErrorDefTime (Exception pEx, string pExtraMessage)
		{
			SetStatus ("Error");

			Log.Error(pEx);

			Dispatcher.Invoke ((Action) (() => { MessageBox.Show (this, (string.IsNullOrWhiteSpace (pExtraMessage) ? string.Empty : pExtraMessage + "\n\n") + GenericException.GetClientMessage (pEx), "Error", MessageBoxButton.OK, MessageBoxImage.Error); }));
		}


		private void SetStatus (string pStatus)
		{
			lblStatusBarText.Dispatcher.Invoke((Action)(() => { lblStatusBarText.Content = pStatus; }));
		}


		private void DropFiles(DragEventArgs e)
		{
			string [] extensions;

			
			e.Effects = DragDropEffects.None;

			extensions = ExtensionFilters;

			extensions = TextHelper.Replace ("*", string.Empty, extensions);

			if (e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				DropFiles (e.Data.GetData (DataFormats.FileDrop) as string []);
			}
		}


		private void DropFiles (params string [] pFileNames)
		{
			if (DataHelper.IsEmpty (pFileNames)) { return; }

			_BgValidate.RunWorkerAsync (pFileNames);
		}


		private void DoDropFiles(object s, DoWorkEventArgs args)
		{
			DoDropFiles (args.Argument as string []);
		}


		private void DoDropFiles (string [] pFileNames)
		{
			string [] extensions;

			FileData currentItem;

			int addCount = 0;
			
			FileRegisterValidatorSet currentValSet;

			FileSystemWatcher newFSW;

			
			ShowClearProgressDialog ();

			CurrentStepName = "Agregando archivos";
			
			extensions = ExtensionFilters;

			extensions = TextHelper.Replace ("*", string.Empty, extensions);

			if (DataHelper.IsEmpty (extensions))
			{
				frmInfoMsg = "No hay extensiones de archivo configuradas para los anexos a los que se le ha dado acceso";
				
				SetAdvanceCompleted ();

				return;
			}

			foreach (string fileName in new List<string>(pFileNames))
			{
				currentValSet = Program.FileRegisterValidatorSets.Find (
						fvs => System.IO.Path.GetFileName (fileName).StartsWith (
							fvs.BaseFileName, 
							StringComparison.InvariantCultureIgnoreCase));

				currentItem = _SelectedFiles.FirstOrDefault (sf => sf.FileInfo.FullName == fileName);

				try
				{
					if (currentItem != null)
					{
						currentItem.Validate ();
					}
					else
					{
						currentItem = new FileData (
							fileName, currentValSet, 
							Log.Session_EnterpriseIdentificationType,
							Log.Session_EnterpriseIdentificationNumber, 
							new CultureInfo (Program.Conf.First (c=>c.Key == "Culture").Value));

						currentItem.Validate ();

						Dispatcher.Invoke ((Action) (() => {
							_SelectedFiles.Add (currentItem); }));

						if (!_FSWatchers.Exists (fsw => fsw.Path == currentItem.Directory.FullName))
						{
							newFSW = new FileSystemWatcher (currentItem.Directory.FullName);

							newFSW.Renamed += new RenamedEventHandler(newFSW_Renamed);
							newFSW.Deleted += new FileSystemEventHandler(newFSW_Deleted);
							newFSW.Changed += new FileSystemEventHandler (newFSW_Changed);

							newFSW.EnableRaisingEvents = true;
							
							_FSWatchers.Add (newFSW);
						}
					}
				}
				catch (Exception pEx)
				{
					Log.Error (pEx);

					Dispatcher.Invoke ((Action) (() => {
						MessageBox.Show (this, string.Format ("La lectura del archivo:\n{0}\nno pudo ser realizada:\n{1}", fileName, pEx.Message), "Error de lectura de archivo", MessageBoxButton.OK, MessageBoxImage.Error); }));
					
					break;
				}

				addCount ++;

				SetAdvance ("Validando.", pFileNames.Length, addCount);
			}

			SetStatus (string.Format ("Validados {0} archivos", addCount));

			Dispatcher.Invoke ((Action) (() => {
				if (chkAutoSendOK.IsChecked.Value)
				{
					UploadFiles ();
				}

				ActiveFileSelectedButtons();
			}));
		}


		private void newFSW_Deleted(object sender, FileSystemEventArgs e)
		{
			FileData item;


			if (!File.Exists(e.FullPath))
			{
				return;
			}
			
			try
			{
				item = _SelectedFiles.FirstOrDefault(f => f.FileInfo.FullName == e.FullPath);

				if (item != null)
				{
					Dispatcher.Invoke((Action)(() => { _SelectedFiles.Remove(item); }));
				}


				Dispatcher.Invoke (
					(Action)(() =>
					{
						// Si la ventana del log correspondiente esta abierta esta debe actualizarse o cerrarse
						if (_ValidationLogViewer.IsVisible && _ValidationLogViewer.FileData.FileInfo.FullName == item.FileInfo.FullName)
						{
							MessageBox.Show(this, string.Format("El archivo:\n\n{0}\n\nYa no esta en la ubicación indicada", item.FileInfo.FullName), "Archivo inexistente", MessageBoxButton.OK, MessageBoxImage.Exclamation);

							_ValidationLogViewer.Close();
						}
					}));
			}
			catch (Exception pEx)
			{
				Log.Error (pEx);
			}
		}


		private void newFSW_Renamed (object sender, RenamedEventArgs e)
		{
			FileData item;


			if (!File.Exists(e.FullPath))
			{
				return;
			}
			
			try
			{
				item = _SelectedFiles.FirstOrDefault(f => f.FileInfo.FullName == e.OldFullPath);

				if (item != null)
				{
					Dispatcher.Invoke ((Action) (() => { _SelectedFiles.Remove(item); }));
				}
				else
				{
					return;
				}

				Dispatcher.Invoke ((Action) (() => { DropFiles (e.FullPath); }));

				Dispatcher.Invoke(
				(Action)(() =>
				{
					// Si la ventana del log correspondiente esta abierta esta debe actualizarse
					if (_ValidationLogViewer.IsVisible && _ValidationLogViewer.FileData.FileInfo.FullName == e.OldFullPath)
					{
						_ValidationLogViewer.FileData = _SelectedFiles.FirstOrDefault(f => f.FileInfo.FullName == e.FullPath);
					}
				}));
			}
			catch (Exception pEx)
			{
				Log.Error (pEx);
			}
		}


		private void newFSW_Changed (object sender, FileSystemEventArgs e)
		{
			FileData item;

			string filePath;


			if (!File.Exists (e.FullPath))
			{
				return;
			}


			if (e.ChangeType == WatcherChangeTypes.Changed)
			{
				filePath = e.FullPath;

				item = _SelectedFiles.FirstOrDefault (sf => sf.FileInfo.FullName == filePath);
				
				if (item != null)
				{
					try
					{
						item.Validate ();
					}
					catch (Exception pEx)
					{
						Log.Error (pEx);
						
						frmErrorMsg = string.Format ("La validación en la lectura de cambios del archivo ha fallado:\n\n{0}\n\nDetalle del Fallo:\n\n{1}", item.FileInfo.FullName, pEx.Message);
					}

					Dispatcher.Invoke (
						(Action) (() =>
						{
							// Si la ventana del log correspondiente esta abierta esta debe actualizarse o cerrarse
							if (_ValidationLogViewer.IsVisible && _ValidationLogViewer.FileData.FileInfo.FullName == item.FileInfo.FullName)
							{
								_ValidationLogViewer.FileData = item;
							}
						}));
				}
			}

			Dispatcher.Invoke (
				(Action) (() =>
				{
					grvSelectedFiles.Items.Refresh ();

					if (chkAutoSendOK.IsChecked.Value)
					{
						UploadFiles();
					}
				}));
		}


		private void UploadFiles (bool pFromButton = false)
		{
			string fileNameTemp;

			bool doSign;
			bool useCER;
			bool useCMS;

			FileData [] fileSet;


			_ValidFileCount = 0;
			_SentFileCount = 0;

			_WasConfirmMsgShowed = false;

			string operationName = string.Empty;

			
			WPFHelper.SetEnabled (btnUploadFiles, false);


			lock (_SelectedFiles)
			{
				#region Validar listado
			
				for (int i = 0; i < _SelectedFiles.Count; i++)
				{
					_SelectedFiles [i].Validate ();
				}

				#endregion

				_ValidFileCount = _SelectedFiles.Where (sf=>sf.IsValid).Count ();
			}
			
			if (_ValidFileCount == 0)
			{
				if (pFromButton)
				{
					frmInfoMsg = "No hay archivos validos para enviar";
				}

				SetAdvanceCompleted ();
				return;
			}
			
			try
			{
				Dispatcher.Invoke ((Action) (() => { Cursor = Cursors.Wait; }));

				SetStatus ("Enviando los archivos en estado OK...");


				lock (_SelectedFiles)
				{
					fileSet = _SelectedFiles.Where(sf => sf.IsValid).ToArray();
				}


				foreach (FileData fileItem in fileSet)
				{
					useCMS = fileItem.ValidatorSet.RequiresCMS;
				

					useCER = (bool) Dispatcher.Invoke ((Func<bool>) (() => { 
							return _ConfigureDigitalFileSign.Config.UseCER; }));


					doSign = (bool) Dispatcher.Invoke ((Func<bool>) (() => { 
						return _ConfigureDigitalFileSign.Config.UseCER; }));


					#region Zip file
						
					fileNameTemp = Path.Combine (ReadConfig.TempDirectory, fileItem.Name + ".zip");

					FileHelper.Delete (fileNameTemp);

					using (ZipFile fileZip = new ZipFile (fileNameTemp))
					{
						fileZip.AddFile (fileItem.FileInfo.FullName, string.Empty);

						fileZip.Save ();
					}

					if (useCMS)
					{
						useCER = false;
						doSign = false;

						#region CMS, Sobre Digital

						// Verificar que la clave publica de la Entidad este registrada					
						CertificateHelper.CreateCMS (_ConfigureDigitalFileSign.SelectedCertificate, 
							ESF.SFT.FileUploader.SharedResources.SharedResources.GetEnterpriseCertificate (), fileNameTemp, fileNameTemp + ".cms");

						fileNameTemp += ".cms";

						#endregion
					}
					else
					{
						#region Firmado Digital

						// Si esta la firma configurada 
						if (useCER)
						{
							doSign = true;
						}
						// Si el anexo la requiere
						else if (fileItem.ValidatorSet.RequiresDigitalCertificate)
						{
							if (!useCER)
							{
								if (fileItem.ValidatorSet.OptionalDigitalCertificate)
								{
									doSign = false;
								}
								else
								{
									throw new GenericInfoException(string.Format("El Archivo {0} requiere de Firma Digital.\n\nConfigure su Certificado antes de poder enviarlo.", fileItem.Name));
								}
							}
						}
						
						if (doSign)
						{
							// Se agrega como atributo del firmado el nombre original del archivo firmado que seria el .zip
							if (!(bool) Dispatcher.Invoke ((Func<bool>) (() => 
							{ 
								try
								{
									fileNameTemp = _ConfigureDigitalFileSign.SignFile (Path.GetFileName (fileNameTemp), fileItem.ValidatorSet.Name, fileNameTemp, true);

									return true;
								}
								catch (Exception pEx)
								{
									Log.Error (pEx);

									frmInfoMsg = string.Format ("No pudo realizarse la Firma Digital, verifique la validez de su Certificado y la configuración correspondiente con su proveedor de Certificados Digitales:\n\n{0}", pEx.Message);

									return false;
								}		
							}))) { return; }
						}

						#endregion
					}

					#endregion

					using (FileStream FS = FileHelper.GetFileStream (fileNameTemp))
					{
						_Presenter._ReceiverClient.UploadFileAsync
						(
							new FileInfo (fileNameTemp).Length,
							Path.GetFileName (fileNameTemp),
							fileItem.IdentificationNumber,
							fileItem.IdentificationTypeCode,
							TextHelper.GetMD5HashFile (fileNameTemp),
							Log.Session_Ticket,
							fileItem.ValidatorSet.BaseFileName,
							Log.Session_UserName,
							FS,
							new string [] { fileItem.FileInfo.FullName, fileNameTemp }
						);
					}
				}
			}
			catch (Exception pEx)
			{
				LogError(pEx);
			}

			Dispatcher.Invoke((Action)(() => { Cursor = Cursors.Arrow; }));
		}


		#region Remueve los validos ya enviados
				
		public void RemoveUploadedFromList(string [] pOriginalFileName_pFileNameTemp)
		{
			string fileNameTemp = pOriginalFileName_pFileNameTemp [1];

			string tmpFile;
			string tmpFileOrigin;

			
			lock (_SelectedFiles)
			{
				for (int i = 0; i < _SelectedFiles.Count; i++)
				{
					if (_SelectedFiles[i].IsValid)
					{
						#region Se mueve si es de la automatica

						if (!string.IsNullOrWhiteSpace(_FolderDialog.SelectedPath)
							&& _SelectedFiles[i].FileInfo.FullName.StartsWith(_FolderDialog.SelectedPath, StringComparison.InvariantCultureIgnoreCase))
						{
							tmpFile = Path.Combine(
									_SelectedFiles[i].FileInfo.DirectoryName,
									ReadConfig.GetAppSetting("AutomaticEntrySentFolderName", "ESF.SFT.SentFiles"),
									_SelectedFiles[i].FileInfo.Name);


							tmpFileOrigin = _SelectedFiles[i].FileInfo.FullName;

							if (File.Exists(tmpFileOrigin))
							{
								FileHelper.Delete(tmpFile);

								FileHelper.EnsureFolder(tmpFile);

								// Se mueve el archivo a una carpeta definida en las appsettings como: AutomaticEntrySentFolderName
								File.Move(tmpFileOrigin, tmpFile);
							}
						}

						#endregion

						else
						{
							Dispatcher.Invoke((Action)(() => { _SelectedFiles.RemoveAt(i); }));

							i--;
						}
					}
				}
			}

			// Borra el Archivo Temporal generado
			FileHelper.Delete(fileNameTemp);


			ClearFSW ();

			Log.StopOps();

			Interlocked.Increment (ref _SentFileCount);
				
			SetAdvance ("Enviando.", _ValidFileCount, _SentFileCount);


			SetStatus(string.Format("Archivos enviados: {0}", _SentFileCount));

			if (_ValidFileCount == _SentFileCount && !_WasConfirmMsgShowed)
			{
				_WasConfirmMsgShowed = true;

				frmInfoMsg = string.Format ("Archivos enviados: {0}" + 
					"\n\nPara estos archivos continuará el proceso de validación de firma o sobre digital (si aplica)." +
					"\nSi esta validación es correcta se enviará al aplicativo misional respectivo, donde se validarán los datos reportados y se notificará a su entidad al correo electrónico:\n{1}", 
						_SentFileCount, Log.Session_EnterpriseEmail);
			}


			ActiveFileSelectedButtons();

			ShowUploadHistory ();
		}

		#endregion


		public void ShowResumen ()
		{
			List<Couple<string, string>> dicResumen;


			dicResumen = _Presenter._ReceiverGeneralClient.GetFileUploadResumen (Log.Session_Ticket, Log.Session_UserName);
				
			//lblTodayFileCount.Content = dicResumen ["TodayFileCount"];
			if (DataHelper.IsEmpty (dicResumen))
			{
				lblgrvUploadFileHistoryCount.Content = "No ha enviado archivos";
			}
			else
			{
				lblgrvUploadFileHistoryCount.Content = string.Format ("Ha enviado {0} archivos", dicResumen.First (c=>c.Key == "TotalFileCount").Value);
			}
		}


		public void LoadConfiguration ()
		{
			StringBuilder extensionsFilter = new StringBuilder ();

			StringBuilder htmlHelpContents = new StringBuilder ();


			Log.CurrentStep = "Carga Configuración Firma Digital";

			
			lblUserName.Content = Log.Session_UserName;

			// TODO: Soportarlo
			//_ConfigureDigitalFileSign.ShowHtmlHelp (htmlHelpContents.ToString ());

			if (DataHelper.IsEmpty (Program.FileRegisterValidatorSets))
			{
				MessageBox.Show(this, "No tiene Anexos Técnicos asignados para realizar el envío de archivos.\nComuniquese con la mesa de ayuda para actualizar estos datos en el Sistema", "Configuracion pendiente", MessageBoxButton.OK, MessageBoxImage.Stop);

				Close ();

				return;
			}
			
			foreach (string ext in ExtensionFilters)
			{
				if (extensionsFilter.Length > 0)
				{
					extensionsFilter.Append ("|");
				}

				extensionsFilter.AppendFormat ("Archivos ({0})|*{0}", ext);
			}			
	
			_FileDialog.Filter = extensionsFilter.ToString ();


			_ConfigureDigitalFileSign.LoadConfiguration();


			_FolderDialog.SelectedPath = Log.ReadStringFileName (Log.Session_UserName, PARTCONF_AUTOENTRYFOLDER);

			ActiveFSWFolderDialog ();


			Log.StopOps ();
		}


		private void PasteFiles ()
		{
			string [] fileNames;

			StringCollection copyFileNames;


			if (Clipboard.ContainsFileDropList ())
			{
				copyFileNames = Clipboard.GetFileDropList ();
				
				fileNames = new string [copyFileNames.Count];

				copyFileNames.CopyTo (fileNames, 0);
				
				DropFiles (fileNames);

				Clipboard.Clear ();
			}
		}


		private void ClearFSW ()
		{
			for (int i = 0; i < _FSWatchers.Count; i++)
			{
				if (_SelectedFiles.FirstOrDefault (sf => sf.Directory.FullName == _FSWatchers [i].Path) == null)
				{
					_FSWatchers [i].EnableRaisingEvents = false;
					_FSWatchers.RemoveAt (i);

					i--;
				}
			}	
		}


		private void SetAutomaticEntryFolder ()
		{
			if (!btnUseAutomaticEntryFolder.IsChecked.Value)
			{
				if (MessageBox.Show (this, "¿Desea detener el uso de la Carpeta de Entrada Automática?", "Confirmación", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
				{
					_FolderDialog.SelectedPath = string.Empty;
				}
			}
			else
			{
				if (_FolderDialog.ShowDialog () == System.Windows.Forms.DialogResult.OK)
				{
					frmInfoMsg = string.Format ("Ha definido la carpeta de Entrada automática como:\n\n{0}\n\nPara dejar de usar esta carpeta de click nuevamente en \"Usar Carpeta Automatica\"", _FolderDialog.SelectedPath);
				}
				else
				{
					_FolderDialog.SelectedPath = string.Empty;

					frmInfoMsg = "Ha cancelado el uso de la Carpeta de Entrada Automática";
				}
			}

			ActiveFSWFolderDialog ();
		}


		private void ActiveFSWFolderDialog ()
		{
			btnUseAutomaticEntryFolder.IsChecked = !string.IsNullOrWhiteSpace(_FolderDialog.SelectedPath) && Directory.Exists (_FolderDialog.SelectedPath);

			if (btnUseAutomaticEntryFolder.IsChecked.Value)
			{
				_FolderDialogFSW.Path = _FolderDialog.SelectedPath;

				_FolderDialogFSW.EnableRaisingEvents = true;

				btnUseAutomaticEntryFolder.Content = "Detener Carpeta Automática"; 
				
				btnUseAutomaticEntryFolder.ToolTip = "Su carpeta automática es: " + _FolderDialog.SelectedPath;

				DoDropFiles (Directory.GetFiles (_FolderDialog.SelectedPath));
			}
			else
			{
				_FolderDialogFSW.EnableRaisingEvents = false;

				btnUseAutomaticEntryFolder.Content = "Usar Carpeta Automática";

				btnUseAutomaticEntryFolder.ToolTip = "Solo para enviar altos volumenes de archivos. Permite configurar una carpeta para que la aplicación monitoree sus archivos y los valide automáticamente";
			}
		}

		#endregion


		#region Button Events

		private void btnUseAutomaticEntryFolder_Click(object sender, RoutedEventArgs e)
		{
			SetAutomaticEntryFolder ();
		}


		private void btngrvUploadFileHistoryPrevious_Click(object sender, RoutedEventArgs e)
		{
			_PaggingInfo.PageIndex --;

			ShowUploadHistory ();
		}

		private void btngrvUploadFileHistoryNext_Click(object sender, RoutedEventArgs e)
		{
			_PaggingInfo.PageIndex ++;

			ShowUploadHistory ();
		}


		private void btnShowUploadHistory_Click (object sender, RoutedEventArgs e)
		{
			ShowUploadHistory ();
		}


		private void btnSelectFiles_Click(object sender, RoutedEventArgs e)
		{
			ShowSelectFiles();
		}


		private void btnClearFiles_Click(object sender, RoutedEventArgs e)
		{
			_SelectedFiles.Clear ();

			ActiveFileSelectedButtons ();
		}


		private void btnUploadFiles_Click(object sender, RoutedEventArgs e)
		{
			ShowClearProgressDialog();
			
			CurrentStepName = "Iniciando carga de archivos...";

			_BgUpload.RunWorkerAsync(true);
		}


		private void btnConfigureDigitalSign_Click(object sender, RoutedEventArgs e)
		{
			_ConfigureDigitalFileSign.Owner = this;			
			_ConfigureDigitalFileSign.ShowDialog ();
		}


		private void btnRemoveFile_Click(object sender, RoutedEventArgs e)
		{
			FileData item;


			for (int i = 0; i < grvSelectedFiles.SelectedItems.Count; i++)
			{
				item = grvSelectedFiles.SelectedItems [i] as FileData;

				_SelectedFiles.Remove (item);

				i--;
			}

			ClearFSW ();

			ActiveFileSelectedButtons ();
		}

		#endregion

		
		#region Window Events

		private void Window_Drop(object sender, DragEventArgs e)
		{
			DropFiles(e);
		}

		#endregion

		
		#region Label Events

		private void lblFilterToday_MouseDown(object sender, MouseButtonEventArgs e)
		{
			dtmStartUploadDate.SelectedDate = DataHelper.SetAsStartDate (DateTime.Now);
			dtmEndUploadDate.SelectedDate = DataHelper.SetAsEndDate (DateTime.Now);
			
			ShowUploadHistory ();
		}


		private void lblFilterClear_MouseDown(object sender, MouseButtonEventArgs e)
		{
			dtmStartUploadDate.SelectedDate = null;
			dtmEndUploadDate.SelectedDate = null;
			
			ShowUploadHistory ();
		}

		#endregion


		#region Window Events

		private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
		{
			PasteFiles ();
		}

		private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
		{
			e.CanExecute = true;
		}

		private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			if (_SelectedFiles.Where (sf => sf.IsValid).Count () > 0)
			{
				if (MessageBox.Show ("Tiene archivos en estado OK (correctos) seleccionados que no ha enviado aun.\n\n¿Desea salir de la aplicación sin enviarlos?", "Archivos OK seleccionados por enviar", MessageBoxButton.YesNo, MessageBoxImage.Warning) == MessageBoxResult.No)
				{
					e.Cancel = true;

					return;
				}
			}

			Log.WriteStringFileName (Log.Session_UserName, PARTCONF_AUTOENTRYFOLDER, _FolderDialog.SelectedPath);

			Application.Current.Shutdown();
		}

		#endregion


		#region Menu Context Events

		private void mengrvSelectedFilesPaste_Click(object sender, RoutedEventArgs e)
		{
			PasteFiles ();
		}


		private void ContextMenu_Opened(object sender, RoutedEventArgs e)
		{
			mengrvSelectedFilesPaste.IsEnabled = Clipboard.ContainsFileDropList ();
		
			if (mengrvSelectedFilesPaste.IsEnabled)
			{
				((Image) mengrvSelectedFilesPaste.Icon).Source = new BitmapImage (new Uri (@"pack://application:,,,/ESF.SFT.FileUploader;component/Images/EditPaste_32x32.png"));
			}
			else
			{
				((Image) mengrvSelectedFilesPaste.Icon).Source = new BitmapImage (new Uri (@"pack://application:,,,/ESF.SFT.FileUploader;component/Images/DisabledEditPaste_32x32.png"));
			}
		}

		#endregion

		
		#region DataGrid Events

		private void grvSelectedFiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)
		{
			FileData item;


			if (e.OriginalSource is TextBlock)
			{
				item = WPFHelper.TryFindParent<DataGridCell> (e.OriginalSource as DependencyObject).DataContext as FileData;
				
				if (item == null) { return; }

				_ValidationLogViewer.FileData = item;

				_ValidationLogViewer.Owner = this;
				_ValidationLogViewer.ShowDialog ();
			}
		}		

		#endregion


		#region ConfigureDigitalFileSign Events
		
		private void _ConfigureDigitalFileSign_Changed (DigitalFileSignConfig pConfigChanged)
		{
			if (pConfigChanged.UseNothing)
			{
				lblFileSignStatus.Content = "No tiene Certificado";
			}
			else
			{
				lblFileSignStatus.Content = "Certificado Digital configurado";
			}
		}

		#endregion


		#region Image Events

		private void imgSessionInfo_MouseDown(object sender, MouseButtonEventArgs e)
		{
			MessageBox.Show (this, Log.Session_Info, "Información de la Sesión", MessageBoxButton.OK, MessageBoxImage.Information);
		}

		#endregion


		#region StatusBar Events

		private void stsStatusBar_DoubleClick (object sender, MouseButtonEventArgs pEvent)
		{
			MessageBox.Show(this,
				Log.GetOperationTimeStatistics(),
				"Tiempos de las operaciones", MessageBoxButton.OK, MessageBoxImage.Information); 
		}

		#endregion


		#region Background Worker Events

		protected void _BgUpload_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			Log.StopOps();

			if (e.Error != null)
			{	
				SetStatusErrorDefTime(e.Error);
				return;
			}

			#region Lista

			dtmStartUploadDate.SelectedDate = null;
			dtmEndUploadDate.SelectedDate = null;

			ShowUploadHistory();
			
			ActiveFileSelectedButtons();

			#endregion
		}


		protected void _BgValidate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			if (e.Error != null)
			{
				Log.StopOps();
				SetStatusErrorDefTime(e.Error);
				return;
			}
		}

		#endregion


		#region Interface Fields

		public string ProductVersion
		{
			set { stsStatusBar.ToolTip = value; }
		}

		#endregion


		#region FSW Events

		private void _FolderDialogFSW_Changed(object sender, FileSystemEventArgs e)
		{
			switch (e.ChangeType)
			{
				case WatcherChangeTypes.Changed:
				case WatcherChangeTypes.Created:
				case WatcherChangeTypes.Renamed:
					
					if (File.Exists (e.FullPath))
					{					
						DoDropFiles (new string [] { e.FullPath });
					}

				break;
			}
		}

		#endregion
	}
}
